<template>
    <div>
        <el-dialog
            class="ba-operate-dialog"
            top="12vh"
            :close-on-click-modal="false"
            :model-value="baTable.form.extend!.id > 0"
            @close="onClose"
            width="50%"
        >
            <template #header>
                <div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">聊天记录</div>
            </template>

            <div class="window-records">
                <!-- 聊天记录 -->
                <TransitionGroup
                    @scroll="transitionGroupScroll($event)"
                    class="chat-records ba-scroll-style"
                    name="el-fade-in-linear"
                    tag="div"
                    :ref="messageScrollbarRef"
                    v-loading="state.loading"
                >
                    <div class="chat-records-grow" key="chatRecordsGrow"></div>
                    <template v-for="(item, idx) in state.records" :key="idx">
                        <div
                            v-for="(message, index) in item.data"
                            :key="message.id ? message.id : message.content"
                            class="chat-record-item"
                            :class="getRecordItemClass(message)"
                        >
                            <span v-if="message.type == 'system'">{{ message.content }}</span>
                            <template v-else>
                                <div class="record-avatar-img">
                                    <img draggable="false" :src="getRecordUserInfo(message.sender_id, 'avatar')" />
                                </div>
                                <div class="record-content-box">
                                    <div class="chat-record-nickname">{{ getRecordUserInfo(message.sender_id, 'nickname') }}</div>
                                    <div class="record-content">
                                        <template v-if="message.type == 'text'">
                                            <div class="text-content">
                                                <MdPreview
                                                    class="message-md-content"
                                                    :id="'content-' + index"
                                                    :editorId="'content-' + index"
                                                    :modelValue="message.content"
                                                />
                                            </div>
                                        </template>
                                        <el-image
                                            :hide-on-click-modal="true"
                                            v-else-if="message.type == 'image'"
                                            :preview-src-list="[fullUrl(message.content)]"
                                            :src="fullUrl(message.content)"
                                            class="record-img"
                                        ></el-image>
                                        <div v-else-if="message.type == 'file'" class="record-file">
                                            <div class="file-suffix">
                                                <img :src="buildSuffixSvgUrl(message.extend.suffix)" alt="" />
                                            </div>
                                            <div class="file-name-box">
                                                <div class="file-name">{{ message.extend.name }}</div>
                                                <div class="file-size">{{ getFileSize(message.extend.size) }}</div>
                                            </div>
                                            <el-button size="small" @click="downloadFile(message.content, message.extend.name)" class="file-download"
                                                >下载</el-button
                                            >
                                        </div>
                                        <el-link target="_blank" type="success" v-else-if="message.type == 'link'" :href="message.content">
                                            {{ message.title ?? message.content }}
                                        </el-link>
                                        <div v-else-if="message.type == 'good'" class="record-card toolbar-data-item">
                                            <img class="data-item-logo" :src="message.extend.logo" />
                                            <div class="data-item-info">
                                                <div class="data-item-title">{{ message.extend.title }}</div>
                                                <div class="data-item-subtitle">{{ message.extend.subtitle }}</div>
                                                <div class="data-item-price">{{ message.extend.price }}</div>
                                            </div>
                                        </div>
                                        <div v-else-if="message.type == 'order'" class="record-card toolbar-data-item">
                                            <img class="data-item-logo" :src="message.extend.logo" />
                                            <div class="data-item-info">
                                                <div class="data-item-title">{{ message.extend.title }}</div>
                                                <div class="data-item-subtitle">{{ message.extend.subtitle }}</div>
                                                <div class="data-item-price">
                                                    {{ message.extend.amount }} <span class="number">x{{ message.extend.number }}</span>
                                                </div>
                                            </div>
                                        </div>
                                        <div v-if="message.status == 'read'" class="read-status">已读</div>
                                    </div>
                                </div>
                            </template>
                        </div>

                        <!-- 日期 -->
                        <div class="chat-record-item system">
                            <span>{{ item.datetime }}</span>
                        </div>
                    </template>
                </TransitionGroup>
            </div>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
import { debounce } from 'lodash-es'
import type baTableClass from '/@/utils/baTable'
import { inject, ref, reactive, onMounted } from 'vue'
import { records } from '/@/api/backend/kefu/index'
import { fullUrl } from '/@/utils/common'
import { buildSuffixSvgUrl } from '/@/api/frontend/kefu/index'
import { MdPreview } from 'md-editor-v3'
import 'md-editor-v3/lib/preview.css'

const baTable = inject('baTable') as baTableClass
const messageScrollbarRef = ref()

const state: {
    page: number
    users: anyObj[]
    records: anyObj[]
    loading: boolean
    nextPage: boolean
    meId: number
} = reactive({
    page: 1,
    users: [],
    records: [],
    loading: false,
    nextPage: true,
    meId: 0,
})

const transitionGroupScroll = debounce((e: Event) => {
    const target = e.target as HTMLDivElement
    const scrollTop = Math.abs(target.scrollTop)
    const scrollHeight = target.scrollHeight
    const clientHeight = target.clientHeight

    if (scrollTop + clientHeight + 10 >= scrollHeight) {
        loadRecords(state.page + 1)
    }
}, 300)

const onClose = () => {
    state.page = 1
    state.nextPage = true
    baTable.form.extend!.id = 0
}

const loadRecords = (page = state.page) => {
    if (state.loading || !state.nextPage || !baTable.form.extend!.id) return

    state.loading = true
    records(baTable.form.extend!.id, page)
        .then((res) => {
            if (res.data.page > 1) {
                state.records = [...state.records, ...res.data.messages]
                state.users = { ...state.users, ...res.data.users }
            } else {
                state.users = res.data.users
                state.records = res.data.messages

                if (!res.data.messages.length) {
                    state.records.push({
                        datetime: '没有更多消息了',
                        data: [],
                    })
                }
            }

            state.page = parseInt(res.data.page)
            state.nextPage = res.data.nextPage
            state.meId = res.data.meId
        })
        .finally(() => {
            state.loading = false
        })
}

onMounted(() => {
    loadRecords()
})

/**
 * 聊天记录项的 class
 */
const getRecordItemClass = (message: anyObj) => {
    if (message.type == 'system') {
        return 'system'
    }
    return message.sender_id == state.meId ? 'me' : 'you'
}

/**
 * 聊天记录用户信息
 */
const getRecordUserInfo = (id: number, key: string) => {
    let value = state.users[id] ? state.users[id][key] : ''
    if (key == 'avatar' && value) {
        value = fullUrl(value)
    }
    return value
}

const getFileSize = (byte: string) => {
    const size = parseFloat(byte)
    const i = Math.floor(Math.log(size) / Math.log(1024))
    return (size / Math.pow(1024, i)).toFixed(i < 1 ? 0 : 2) + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i]
}

const downloadFile = (url: string, name: string) => {
    const a = document.createElement('a')
    a.href = url
    a.download = name
    a.click()
}
</script>

<style scoped lang="scss">
:deep(.ba-operate-dialog) {
    .el-dialog__body {
        padding: 0 10px 10px 10px;
    }
}
.window-records {
    position: relative;
    height: 100%;
}
.message-md-content {
    background: transparent;
    :deep(.default-theme p) {
        padding: 0;
        line-height: 1.3;
    }
    :deep(.md-editor-preview) {
        font-size: 15px;
    }
    :deep(.md-editor-preview-wrapper) {
        padding: 0;
        overflow: hidden;
    }
    :deep(.default-theme ul li) {
        margin: 0;
    }
    :deep(a) {
        color: var(--el-color-primary);
        text-decoration: none;
        &:hover {
            text-decoration: underline;
        }
    }
}
.me {
    .message-md-content {
        :deep(.default-theme) {
            --md-theme-color: var(--el-color-white);
            --md-theme-code-inline-color: var(--el-color-black);
            --md-theme-bg-color-inset: #fff;
            blockquote {
                color: #000;
            }
            a {
                color: var(--el-color-warning);
            }
        }
    }
}
.chat-records {
    display: flex;
    flex-direction: column-reverse;
    height: 100%;
    padding: 0 5px 10px 10px;
    overflow-y: auto;
    overflow-x: hidden;
    box-sizing: border-box;
    .chat-records-grow {
        flex-grow: 1;
        flex-shrink: 1;
    }
    .chat-record-item {
        display: flex;
        padding-top: 16px;
        align-items: flex-start;
    }
    .system span {
        font-size: 12px;
        display: inline-block;
        background: var(--el-color-info-light-8);
        color: var(--el-text-color-primary);
        line-height: 12px;
        border-radius: 5px;
        padding: 5px 10px 3px 10px;
        text-align: center;
        word-wrap: break-word;
        word-break: break-all;
        margin: 0 auto;
    }
    .record-avatar-img {
        position: relative;
        display: inline-block;
        background: transparent;
        width: 36px;
        height: 36px;
        cursor: pointer;
        user-select: none;
        img {
            height: 100%;
            width: 100%;
            border-radius: 6px;
        }
    }
    .record-content-box {
        position: relative;
        max-width: 75%;
        margin: 0 13px;
    }
    .me {
        flex-direction: row-reverse;
        display: flex;
        justify-content: flex-start;
        align-content: center;
    }
    .chat-record-nickname {
        color: var(--el-text-color-secondary);
        padding-bottom: 3px;
    }
    .you .chat-record-nickname {
        text-align: left;
    }
    .you .record-content {
        color: #000;
        background: var(--el-color-info-light-9);
        .el-link {
            --el-link-text-color: var(--el-color-success);
        }
    }
    .me .chat-record-nickname {
        text-align: right;
    }
    .me .record-content {
        margin-left: auto;
        color: var(--el-color-white);
        background: var(--el-color-primary);
        .el-link {
            --el-link-text-color: var(--el-color-warning);
            &:hover {
                --el-link-hover-text-color: var(--el-color-warning);
            }
        }
    }
    .you .record-content-box:before {
        left: -4px;
        background: var(--el-color-info-light-9);
    }
    .me .record-content-box:before {
        right: -4px;
        background: var(--el-color-primary);
    }
    .me .data-item-price {
        .number {
            color: #fff;
        }
    }
    .record-content-box:before {
        position: absolute;
        top: 26px;
        display: block;
        width: 8px;
        height: 6px;
        content: '\00a0';
        -webkit-transform: rotate(29deg) skew(-35deg);
        transform: rotate(29deg) skew(-35deg);
    }
    .record-content {
        font-size: 14px;
        color: var(--el-text-color-primary);
        padding: 12px 10px;
        border-radius: 5px;
        position: relative;
        width: fit-content;
        word-wrap: break-word;
        word-break: break-all;
        .record-img,
        .el-image {
            vertical-align: bottom;
            max-width: 200px;
            max-height: 200px;
            width: auto;
            height: auto;
            cursor: pointer;
            user-select: none;
            border: 1px solid transparent;
        }
        .record-file {
            display: flex;
            align-items: center;
            .file-suffix {
                img {
                    width: 40px;
                }
            }
            .file-name-box {
                padding: 0 10px;
                .file-name {
                    font-weight: bold;
                }
                .file-size {
                    padding-top: 4px;
                }
            }
        }
        .text-content {
            display: flex;
            align-items: center;
        }
        .record-card {
            width: 300px;
        }
    }
    .me .read-status {
        position: absolute;
        left: -30px;
        bottom: 0;
        font-size: 12px;
        color: var(--el-color-info);
    }
    .you .read-status {
        position: absolute;
        right: -30px;
        bottom: 0;
        font-size: 12px;
        color: var(--el-color-info);
    }
}
.toolbar-data-item {
    display: flex;
    align-items: center;
    padding: 10px;
    cursor: pointer;
    .data-item-logo {
        width: 80px;
        object-fit: cover;
    }
    .data-item-info {
        display: block;
        padding: 0 10px;
        width: calc(100% - 93px);
        .data-item-title {
            height: 32px;
            font-size: 14px;
            display: block;
            overflow: hidden;
            text-overflow: ellipsis;
            display: -webkit-box;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2;
            line-clamp: 2;
            line-height: 16px;
            font-weight: bold;
        }
        .data-item-subtitle {
            display: block;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            margin-top: 2px;
        }
        .data-item-price {
            margin-left: -3px;
            font-size: 18px;
            color: rgba(231, 76, 60, 1);
            .number {
                color: #999999;
                font-size: 14px;
            }
        }
    }
    .data-item-radio {
        width: 13px;
    }
}
</style>
